package com.liujit.pay.wx.api;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.liujit.pay.common.domain.result.PayResult;
import com.liujit.pay.common.enums.RequestMethod;
import com.liujit.pay.common.enums.SignType;
import com.liujit.pay.common.util.PayUtil;
import com.liujit.pay.wx.domain.params.order.APPOrderParam;
import com.liujit.pay.wx.domain.params.order.H5OrderParam;
import com.liujit.pay.wx.domain.params.order.JSAPIOrderParam;
import com.liujit.pay.wx.domain.params.order.NativeOrderParam;
import com.liujit.pay.wx.domain.result.APPOrderResult;
import com.liujit.pay.wx.domain.result.H5OrderResult;
import com.liujit.pay.wx.domain.result.JSAPIOrderResult;
import com.liujit.pay.wx.domain.result.NativeOrderResult;
import com.liujit.pay.wx.enums.PayApi;
import com.liujit.pay.wx.enums.ReturnCode;
import com.liujit.pay.wx.kit.HttpKit;
import com.liujit.pay.wx.kit.WxPayKit;

import java.util.ArrayList;
import java.util.List;

/**
 * @description: 微信支付相关接口
 * @author: liujun
 * @create: 2021-02-20 11:40
 */
public class WxOrderApi {

    /**
     * JSAPI支付/小程序支付
     *
     * @param param
     * @return
     */
    public static PayResult jsapiOrder(JSAPIOrderParam param) {
        // 请求参数
        String body = param.toJSONString();
        // 发送请求
        String resp = order(body, PayApi.JSAPI_ORDER, param.getMchId(), param.getKeyPath(), param.getSerialNo());
        JSONObject respJson = JSONUtil.parseObj(resp);
        ReturnCode returnCode = ReturnCode.getReturnCode(respJson.getStr("code"));
        if (returnCode != null) {
            return new PayResult(returnCode.getCode(), returnCode.getMessage());
        }
        JSAPIOrderResult result = new JSAPIOrderResult();
        // 应用ID
        result.setAppId(param.getAppId());
        // 时间戳
        result.setTimeStamp(Convert.toStr(PayUtil.generateTimestamp()));
        // 随机字符串
        result.setNonceStr(PayUtil.generateNonceStr());
        // 订单详情扩展字符串
        result.setPackageStr("prepay_id=" + respJson.getStr("prepay_id"));
        // 签名方式
        result.setSignType(SignType.RSA.getType());
        // 签名
        List<String> signMessage = new ArrayList<>();
        signMessage.add(result.getAppId());
        signMessage.add(result.getTimeStamp());
        signMessage.add(result.getNonceStr());
        signMessage.add(result.getPackageStr());
        String paySign = WxPayKit.createSign(signMessage, param.getKeyPath());
        result.setPaySign(paySign);
        return new PayResult(result);
    }

    /**
     * APP支付
     *
     * @param param
     * @return
     */
    public static PayResult appOrder(APPOrderParam param) {
        // 请求参数
        String body = param.toJSONString();
        // 发送请求
        String resp = order(body, PayApi.APP_ORDER, param.getMchId(), param.getKeyPath(), param.getSerialNo());
        JSONObject respJson = JSONUtil.parseObj(resp);
        ReturnCode returnCode = ReturnCode.getReturnCode(respJson.getStr("code"));
        if (returnCode != null) {
            return new PayResult(returnCode.getCode(), returnCode.getMessage());
        }
        APPOrderResult result = new APPOrderResult();
        // 应用ID
        result.setAppId(param.getAppId());
        // 商户号
        result.setPartnerId(param.getMchId());
        // 预支付交易会话ID
        result.setPrepayId(respJson.getStr("prepay_id"));
        // 订单详情扩展字符串
        result.setPackageStr("Sign=WXPay");
        // 时间戳
        result.setTimeStamp(Convert.toStr(PayUtil.generateTimestamp()));
        // 随机字符串
        result.setNonceStr(PayUtil.generateNonceStr());
        // 签名
        List<String> signMessage = new ArrayList<>();
        signMessage.add(result.getAppId());
        signMessage.add(result.getTimeStamp());
        signMessage.add(result.getNonceStr());
        signMessage.add(result.getPrepayId());
        String sign = WxPayKit.createSign(signMessage, param.getKeyPath());
        result.setSign(sign);
        return new PayResult(result);
    }

    /**
     * H5支付
     *
     * @param param
     * @return
     */
    public static PayResult h5Order(H5OrderParam param) {
        // 请求参数
        String body = param.toJSONString();
        // 发送请求
        String resp = order(body, PayApi.H5_ORDER, param.getMchId(), param.getKeyPath(), param.getSerialNo());
        JSONObject respJson = JSONUtil.parseObj(resp);
        ReturnCode returnCode = ReturnCode.getReturnCode(respJson.getStr("code"));
        if (returnCode != null) {
            return new PayResult(returnCode.getCode(), returnCode.getMessage());
        }
        H5OrderResult result = new H5OrderResult();
        result.setH5Url(respJson.getStr("h5_url"));
        return new PayResult(result);
    }

    /**
     * H5支付
     *
     * @param param
     * @return
     */
    public static PayResult nativeOrder(NativeOrderParam param) {
        // 请求参数
        String body = param.toJSONString();
        // 发送请求
        String resp = order(body, PayApi.NATIVE_ORDER, param.getMchId(), param.getKeyPath(), param.getSerialNo());
        JSONObject respJson = JSONUtil.parseObj(resp);
        ReturnCode returnCode = ReturnCode.getReturnCode(respJson.getStr("code"));
        if (returnCode != null) {
            return new PayResult(returnCode.getCode(), returnCode.getMessage());
        }
        NativeOrderResult result = new NativeOrderResult();
        result.setCodeUrl(respJson.getStr("code_url"));
        return new PayResult(result);
    }

    /**
     * 发送请求
     *
     * @param body     请求参数
     * @param payApi   请求地址
     * @param mchId
     * @param keyPath
     * @param serialNo
     * @return
     */
    private static String order(String body, PayApi payApi, String mchId, String keyPath, String serialNo) {
        // 获取请求签名
        String authorization = WxPayKit.buildAuthorization(RequestMethod.POST, payApi.getApi(), mchId, serialNo, keyPath, body);
        // 发送请求
        return HttpKit.post(WxPayKit.getReqUrl(payApi), authorization, serialNo, body);
    }
}
